﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Security.Cryptography;

namespace HTTPPlay
{
    class SimpleHCPIO_Native
    {
        static String HCPUserName = "test";
        static String HCPPassword = "project123";

        static string GetStringValue(byte[] Byte)
        {
            string tmpString = "";
            //if (this.isReturnNum == false)
            //{
            //    ASCIIEncoding Asc = new ASCIIEncoding();
            //    tmpString = Asc.GetString(Byte);
            //}
            //else
            //{
                int iCounter;
                for (iCounter = 0; iCounter < Byte.Length; iCounter++)
                {
                    tmpString = tmpString + Byte[iCounter].ToString();
                }
            //}
            return tmpString;
        }

        static byte[] GetKeyByteArray(string strKey)
        {

            ASCIIEncoding Asc = new ASCIIEncoding();

            int tmpStrLen = strKey.Length;
            byte[] tmpByte = new byte[tmpStrLen - 1];

            tmpByte = Asc.GetBytes(strKey);

            return tmpByte;

        }


        static String MD5Encode(String inString)
        {
            MD5CryptoServiceProvider hasher = new MD5CryptoServiceProvider();

            byte[] tBytes = Encoding.ASCII.GetBytes(inString);
            byte[] hBytes = hasher.ComputeHash(tBytes);

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hBytes.Length; i++)
                sb.AppendFormat("{0:x2}", hBytes[i]);

            return sb.ToString();
        }

        static string SHA256Encrypt(string strIN)
        {
            //string strIN = getstrIN(strIN);
            byte[] tmpByte;
            SHA256 sha256 = new SHA256Managed();

            tmpByte = sha256.ComputeHash(GetKeyByteArray(strIN));
            sha256.Clear();

            return GetStringValue(tmpByte);

        }

        static String Base64Encode(String inString)
        {
            byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(inString);

            return System.Convert.ToBase64String(toEncodeAsBytes);
        }

        static public bool AcceptAllCertifications(object sender, 
            System.Security.Cryptography.X509Certificates.X509Certificate certification, 
            System.Security.Cryptography.X509Certificates.X509Chain chain, 
            System.Net.Security.SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

        void do_write(String dstFolderPath, String inFileName) {

            /**
             * Setup the Create (PUT) Web Request.
             **/
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(dstFolderPath + "/" + inFileName);
            request.Method = WebRequestMethods.Http.Put;

            // Setup the request so that the whole object is not loaded in memory.
            request.AllowWriteStreamBuffering = false;
            request.SendChunked = true;

            request.AllowAutoRedirect = false;  // Important because authentication error causes a redirect to occur.

            string sHeader = "HCP " + Base64Encode(HCPUserName) + ":" + MD5Encode(HCPPassword);
            request.Headers.Add("Authorization", sHeader);

            // Put the content into the data stream for the PUT request.
            //  NOTE: Would be more flexible if used the request stream callback mechanism to 
            //     avoid pulling the whole object into memory.
            using (Stream dataStream = request.GetRequestStream())
            {
                // Open the file from disk and put it into the Requst Stream.
                using (FileStream fileStreamToRead = System.IO.File.OpenRead(inFileName + ".toHCP"))
                {
                    fileStreamToRead.CopyTo(dataStream); // Copy File stream into Request Stream.
                }
            }

            /**
             * Execute the Create (PUT) request.
             * 
             *   Needs to be in a "try" block because exection of the request may trigger
             *   a WebException. This sample also translates some non-exeception driven
             *   status codes into exceptions.
             **/
            try
            {
                // Perform HTTP request.
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                switch (response.StatusCode)
                {
                    case HttpStatusCode.Created:
                        Console.WriteLine("File Uploaded");
                        break;
                    case HttpStatusCode.Found:
                        response.Close(); // Clean up response resources.
                        throw new WebException("Authentication Failure with HCP. HttpStatus: " + response.StatusCode + " (" + response.StatusDescription + ")");
                    default:
                        response.Close(); // Clean up response resources.
                        throw new WebException("Unexpected HTTP Response Code: " + response.StatusCode + " (" + response.StatusDescription + ")");
                }

                // Done with Response.
                response.Close();
            }
            catch (WebException ex)
            {
                // If we have a response to interrogate, let's do so.
                if (null != ex.Response)
                {
                    HttpWebResponse response = (HttpWebResponse)ex.Response;
                    HttpStatusCode statusCode = response.StatusCode;
                    String statusDescription = response.StatusDescription;

                    response.Close(); // Clean up response resources

                    switch (statusCode)
                    {
                        case HttpStatusCode.Conflict:
                            throw new WebException("Object already exists on HCP. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                        case HttpStatusCode.Forbidden:
                            throw new WebException("Operation requested is not allowed. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                    }
                }

                throw ex; // Just throw back to the caller.
            }
        }

        void do_write_cm(String dstFolderPath, String inFileName)
        {
            //inFileName = "test.txt";
            /**
             * Setup the Create (PUT) Web Request.
             **/
             
            UriBuilder myURI = new UriBuilder(dstFolderPath + "/" + inFileName);
            myURI.Query = "type=custom-metadata";

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(myURI.Uri);
            request.Method = WebRequestMethods.Http.Put;

            request.AllowAutoRedirect = false;  // Important because authentication error causes a redirect to occur in pre-5.0

            string sHeader = "HCP " + Base64Encode(HCPUserName) + ":" + MD5Encode(HCPPassword);
            request.Headers.Add("Authorization", sHeader);

            // Put the content into the data stream for the PUT request.
            using (Stream dataStream = request.GetRequestStream())
            {
                // Open the file from disk and put it into the Requst Stream.
                using (FileStream fileStreamToRead = System.IO.File.OpenRead("metadata.xml"))
                {
                    fileStreamToRead.CopyTo(dataStream); // Copy File stream into Request Stream.
                }
            }

            /**
             * Execute the Create (PUT) request.
             * 
             *   Needs to be in a "try" block because exection of the request may trigger
             *   a WebException. This sample also translates some non-exeception driven
             *   status codes into exceptions.
             **/
            try
            {
                // Perform HTTP request.
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                switch (response.StatusCode)
                {
                    case HttpStatusCode.Created:
                        Console.WriteLine("Custom Metadata Uploaded");
                        break;
                    case HttpStatusCode.Found:
                        response.Close(); // Clean up response resources.
                        throw new WebException("Authentication Failure with HCP. HttpStatus: " + response.StatusCode + " (" + response.StatusDescription + ")");
                    default:
                        response.Close(); // Clean up response resources.
                        throw new WebException("Unexpected HTTP Response Code: " + response.StatusCode + " (" + response.StatusDescription + ")");
                }

                // Done with Response.
                response.Close();
            }
            catch (WebException ex)
            {
                // If we have a response to interrogate, let's do so.
                if (null != ex.Response)
                {
                    HttpWebResponse response = (HttpWebResponse)ex.Response;
                    HttpStatusCode statusCode = response.StatusCode;
                    String statusDescription = response.StatusDescription;

                    response.Close(); // Clean up response resources

                    switch (statusCode)
                    {
                        case HttpStatusCode.Conflict:
                            throw new WebException("Object already exists on HCP. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                        case HttpStatusCode.Forbidden:
                            throw new WebException("Operation requested is not allowed. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                    }
                }

                throw ex; // Just throw back to the caller.
            }
        }

        void do_read(String dstFolderPath, String inFileName)
        {

            /**
             * Setup for the read (GET) request.
             **/
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(dstFolderPath + "/" + inFileName);
            request.Method = WebRequestMethods.Http.Get;

            request.AllowAutoRedirect = false;  // Important because authentication error causes a redirect to occur.

            string sHeader = "HCP " + Base64Encode(HCPUserName) + ":" + MD5Encode(HCPPassword);
            request.Headers.Add("Authorization", sHeader);

            /**
             * Execute read (GET) request
             * 
             *   Needs to be in a "try" block because exection of the request may trigger
             *   a WebException. This sample also translates some non-exeception driven
             *   status codes into exceptions.
             **/
            try
            {
                // Execute the request.
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                switch (response.StatusCode)
                {
                    case HttpStatusCode.OK:
                        Console.WriteLine("File Retrieved");
                        break;
                    case HttpStatusCode.Found:
                        response.Close(); // Clean up response resources.
                        throw new WebException("Authentication Failure with HCP. HttpStatus: " + response.StatusCode + " (" + response.StatusDescription + ")");
                    default:
                        response.Close(); // Clean up response resources.
                        throw new WebException("Unexpected HTTP Response Code: " + response.StatusCode + " (" + response.StatusDescription + ")");
                }

                // Extract the file from the response and put into disk file.
                using (Stream responseStream = response.GetResponseStream())
                {
                    // Open the file from disk and put it into the Requst Stream.
                    using (FileStream localFileStream = File.OpenWrite(inFileName + ".fromHCP"))
                    {
                        responseStream.CopyTo(localFileStream);
                    }
                }

                // Clean up the response.
                response.Close();
            }
            catch (WebException ex)
            {
                // If we have a response to interrogate, let's do so.
                if (null != ex.Response)
                {
                    HttpWebResponse response = (HttpWebResponse)ex.Response;
                    HttpStatusCode statusCode = response.StatusCode;
                    String statusDescription = response.StatusDescription;

                    response.Close(); // Clean up response resources

                    switch (statusCode)
                    {
                        case HttpStatusCode.Conflict:
                            throw new WebException("Object already exists on HCP. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                        case HttpStatusCode.Found:
                            throw new WebException("Object does not exist. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                        case HttpStatusCode.Forbidden:
                            throw new WebException("Operation requested is not allowed. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                    }
                }

                throw ex; // Just throw back to the caller.
            }
        }

        void do_read_cm(String dstFolderPath, String inFileName)
        {

            /**
             * Setup for the read (GET) request.
             **/
            UriBuilder myURI = new UriBuilder(dstFolderPath + "/" + inFileName);
            myURI.Query = "type=custom-metadata";

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(myURI.Uri);
            request.Method = WebRequestMethods.Http.Get;

            request.AllowAutoRedirect = false;  // Important because authentication error causes a redirect to occur.

            string sHeader = "HCP " + Base64Encode(HCPUserName) + ":" + MD5Encode(HCPPassword);
            request.Headers.Add("Authorization", sHeader);

            /**
             * Execute read (GET) request
             * 
             *   Needs to be in a "try" block because exection of the request may trigger
             *   a WebException. This sample also translates some non-exeception driven
             *   status codes into exceptions.
             **/
            try
            {
                // Execute the request.
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                switch (response.StatusCode)
                {
                    case HttpStatusCode.OK:
                        Console.WriteLine("File Retrieved");
                        break;
                    case HttpStatusCode.Found:
                        response.Close(); // Clean up response resources.
                        throw new WebException("Authentication Failure with HCP. HttpStatus: " + response.StatusCode + " (" + response.StatusDescription + ")");
                    default:
                        response.Close(); // Clean up response resources.
                        throw new WebException("Unexpected HTTP Response Code: " + response.StatusCode + " (" + response.StatusDescription + ")");
                }

                // Extract the file from the response and put into disk file.
                using (Stream responseStream = response.GetResponseStream())
                {
                    // Open the file from disk and put it into the Requst Stream.
                    using (FileStream localFileStream = File.OpenWrite(inFileName + ".fromHCP.cm"))
                    {
                        responseStream.CopyTo(localFileStream);
                    }
                }

                // Clean up the response.
                response.Close();
            }
            catch (WebException ex)
            {
                // If we have a response to interrogate, let's do so.
                if (null != ex.Response)
                {
                    HttpWebResponse response = (HttpWebResponse)ex.Response;
                    HttpStatusCode statusCode = response.StatusCode;
                    String statusDescription = response.StatusDescription;

                    response.Close(); // Clean up response resources

                    switch (statusCode)
                    {
                        case HttpStatusCode.Conflict:
                            throw new WebException("Object already exists on HCP. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                        case HttpStatusCode.Found:
                            throw new WebException("Object does not exist. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                        case HttpStatusCode.Forbidden:
                            throw new WebException("Operation requested is not allowed. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                    }
                }

                throw ex; // Just throw back to the caller.
            }
        }

        void do_delete(String dstFolderPath, String inFileName)
        {

            /**
             * Setup the DELETE Web Request.
             **/
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(dstFolderPath + "/" + inFileName);
            request.Method = "DELETE";

            request.AllowAutoRedirect = false;  // Important because authentication error causes a redirect to occur.

            string sHeader = "HCP " + Base64Encode(HCPUserName) + ":" + MD5Encode(HCPPassword);
            request.Headers.Add("Authorization", sHeader);

            /**
             * Execute the Delete request.
             * 
             *   Needs to be in a "try" block because exection of the request may trigger
             *   a WebException. This sample also translates some non-exeception driven
             *   status codes into exceptions.
             **/
            try
            {
                // Perform HTTP request.
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                switch (response.StatusCode)
                {
                    case HttpStatusCode.OK:
                        Console.WriteLine("File Deleted");
                        break;
                    case HttpStatusCode.Found:
                        response.Close(); // Clean up response resources.
                        throw new WebException("Authentication Failure with HCP. HttpStatus: " + response.StatusCode + " (" + response.StatusDescription + ")");
                    default:
                        response.Close(); // Clean up response resources.
                        throw new WebException("Unexpected HTTP Response Code: " + response.StatusCode + " (" + response.StatusDescription + ")");
                }

                // Done with Response.
                response.Close();
            }
            catch (WebException ex)
            {
                // If we have a response to interrogate, let's do so.
                if (null != ex.Response)
                {
                    HttpWebResponse response = (HttpWebResponse)ex.Response;
                    HttpStatusCode statusCode = response.StatusCode;
                    String statusDescription = response.StatusDescription;

                    response.Close(); // Clean up response resources

                    switch (statusCode)
                    {
                        case HttpStatusCode.Conflict:
                            throw new WebException("Object already exists on HCP. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                        case HttpStatusCode.Forbidden:
                            throw new WebException("Operation requested is not allowed. HttpStatus: " + statusCode + " (" + statusDescription + ")");
                    }
                }

                throw ex; // Just throw back to the caller.
            }
        }

        static void Main(string[] args)
        {
            SimpleHCPIO_Native myObject = new SimpleHCPIO_Native();

            try
            {
                // Setup SSL to accept all certificates for WebRequests.
                ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);

                //myObject.do_write(args[1], args[0]);

                myObject.do_write_cm(args[1], args[0]);

                //myObject.do_read(args[1], args[0]);

                //myObject.do_read_cm(args[1], args[0]);
                
                //myObject.do_delete(args[1], args[0]);
            }
            catch (WebException ex)
            {
                Console.WriteLine(ex.ToString());
                Console.ReadKey();
            }
        }
    }
}
